<template>
  <div>
    <BasicModal
      v-bind="$attrs"
      @register="register"
      :title="title ? `${title} - ${FormModeEntityRef.Display}` : FormModeEntityRef.Display"
      :cancelText="cancelText ? cancelText : t('common.cancelText')"
      :close-func="handleClose"
      :okText="okText ? okText : FormModeEntityRef.OkBtnTitle"
      @ok="handleOk"
      @keypress.enter="handleOk"
    >
      <BasicForm @register="registerForm" />
    </BasicModal>
  </div>
</template>
<script lang="ts">
  import { PropType, unref, defineComponent, ref } from 'vue';
  import { BasicModal, useModalInner } from '@/components/Modal';
  import { BasicForm, useForm, FormSchema } from '@/components/Form';
  import { useI18n } from '@/hooks/web/useI18n';
  import { useMessage } from '@/hooks/web/useMessage';

  import { isFunction, isArray, isObject } from '@/utils/is';
  import { propTypes } from '@/utils/propTypes';

  import { FormModeEnum, FormModeEntity } from '@/enums/formEnum';

  import { FetchParams } from '@/components/Table';
  import { AjaxResult } from '@/api/model';
  import { List } from '@/components/Linqts';
  import { GetMaterialTreeNodes, GetDictNodes, Create } from './ipn.api';
  import { getStatusSchema } from './ipn.enum';
  import { usePermission } from '@/hooks/web/usePermission';
  import IPNSelectDrawer from './IPNSelectDrawer.vue';

  const { hasPermission } = usePermission();
  const statusEnumSchema = getStatusSchema();
  export default defineComponent({
    name: 'IPNDetailFormModal',
    components: {
      BasicModal,
      BasicForm,
      IPNSelectDrawer,
    },
    props: {
      /** 表单标识 */
      formIndex: propTypes.string,
      /** 主键字段 */
      keyField: propTypes.string.def('Id'),
      /** 表单抬头 */
      title: propTypes.string,
      /** 关闭按钮文本 */
      cancelText: propTypes.string,
      /** 确认按钮文本 */
      okText: propTypes.string,
      /** 表单架构 */
      formSchema: {
        type: [Array] as PropType<FormSchema[]>,
        default: () => [],
      },
      /** 扩展 form 组件，增加 label 宽度，表单内所有组件适用，可以单独在某个项覆盖或者禁用 */
      labelWidth: {
        type: [Number, String] as PropType<number | string>,
        default: null,
      },
      /** label 布局 */
      labelAlign: {
        type: String as PropType<'left' | 'right'>,
        default: null,
      },
      /** 紧凑类型表单，减少 margin-bottom */
      compact: propTypes.bool.def(true),
      /** 向表单内所有组件传递 size 参数,自定义组件需自行实现 size 接收 */
      size: {
        type: String as PropType<'default' | 'small' | 'large'>,
        default: null,
      },
      /** 向表单内所有组件传递 disabled 属性，自定义组件需自行实现 disabled 接收 */
      disabled: propTypes.bool,
      /** 实体新增接口请求对象 */
      createApi: {
        type: Function as PropType<(params: any[]) => Promise<any>>,
        default: null,
      },
      /** 实体更新接口请求对象 */
      updateApi: {
        type: Function as PropType<(params: any[]) => Promise<any>>,
        default: null,
      },
      /** 实体删除接口请求对象 */
      deleteApi: {
        type: Function as PropType<(params: any[]) => Promise<any>>,
        default: null,
      },
      /** 关闭回调，返回true关闭窗体 */
      closeFunc: {
        type: Function as PropType<(formMode: FormModeEnum, record: any) => Promise<boolean>>,
        default: null,
      },
      /** 提交回调，返回true关闭窗体 */
      submitFunc: {
        type: Function as PropType<(formMode: FormModeEnum, record: any) => Promise<boolean>>,
        default: null,
      },
      /** 重新加载表格数据方法 */
      reloadFunc: {
        type: Function as PropType<(opt?: FetchParams) => Promise<Recordable<any>[] | undefined>>,
        default: null,
      },
    },
    setup(props) {
      const { t } = useI18n();
      const { createMessage } = useMessage();
      const formModeRef = ref<FormModeEnum>(FormModeEnum.Ok);
      const FormModeEntityRef = ref<FormModeEntity>(new FormModeEntity(formModeRef.value));
      const materialsRef = ref<List<any>>(new List());
      const descRef = ref<List<any>>(new List());

      const toMaterialArray = function (data) {
        if (isArray(data) && (data as Array<any>).length > 0) {
          new List(data).ForEach((i) => {
            materialsRef.value.Add(i);
            //@ts-ignore
            toMaterialArray(i.Children);
          });
        }
        return;
      };

      const schemas: FormSchema[] = [
        {
          field: 'Id',
          label: '主键',
          helpMessage: '',
          component: 'Input',
          componentProps: {
            disabled: true,
          },
        },
        // {
        //   field: 'IPN',
        //   label: 'IPN号',
        //   required: true,
        //   helpMessage: '',
        //   component: 'Input',
        //   componentProps: {

        //   },
        //   ifShow: () => {
        //     return hasPermission('Admin.Wms.IPN.ApplyIpnToComplete');
        //   },
        //   colProps: {
        //     offset: 3,
        //     // span: 24,
        //     xs: 16, // <576px
        //     sm: 16, // ≥576px
        //     md: 16, // ≥768px
        //     lg: 16, // ≥992px
        //     xl: 16, // ≥1200px
        //     xxl: 16, // ≥1600px
        //     // xxxl: 24, // ≥2000px 3.0
        //   },
        // },
        {
          field: 'Status',
          label: '状态',
          component: 'Select',
          componentProps: {
            disabled: true,
            options: statusEnumSchema,
            showSearch: true,
            optionFilterProp: 'label',
            style: {
              width: '100%',
            },
          },
        },
        {
          field: 'MaterialCategoryId',
          label: '物料分类',
          helpMessage: '',
          required: true,
          component: 'ApiTreeSelect',
          componentProps: {
            api: async () => {
              const result: AjaxResult = await GetMaterialTreeNodes();
              if (result.Data && isArray(result.Data)) {
                result.Data.forEach((a) => {
                  if (a.Level == 1) {
                    a.disabled = true;
                  }
                });
              }
              toMaterialArray(result.Data);
              return result;
            },
            resultField: 'Data',
            labelField: 'Name',
            valueField: 'Id',
            childrenField: 'Children',
            treeNodeFilterProp: 'Name',
            onChange: (e, arr) => {
              // const material = unref(materialsRef).FirstOrDefault(a => a.Id == e);
              // if (material && material.Level == 3 && material.Description) {
              //   const arr = material.Description.split(',');
              //   setDefaultDescription(arr);
              // }
              // else {
              //   setFieldsValue({
              //     Description: ''
              //   })
              // }
              // console.log('selected:', material);
            },
          },
        },
        {
          field: 'Name',
          label: '部件型号/名称',
          required: true,
          component: 'Input',
        },
        {
          field: 'Description',
          label: '规格型号/描述',
          required: false,
          component: 'InputTextArea',
          componentProps: {},
        },
        {
          field: 'Unit',
          label: '单位',
          helpMessage: '',
          required: true,
          component: 'ApiSelect',
          componentProps: {
            api: GetDictNodes,
            params: 'unit',
            resultField: 'Data',
            // use name as label
            labelField: 'CodeName',
            // use id as value
            valueField: 'CodeValue',
            immediate: true,
            optionFilterProp: 'label',
            showSearch: true,
          },
        },
        {
          field: 'Manufacturer',
          label: '生产商',
          required: false,
          component: 'Input',
          componentProps: {},
        },
        {
          field: 'StockAttributes',
          label: '存货属性',
          required: true,
          component: 'InputTextArea',
          componentProps: {},
        },
        {
          field: 'Project',
          label: '所属项目',
          required: true,
          component: 'ApiSelect',
          componentProps: {
            api: GetDictNodes,
            params: 'project',
            resultField: 'Data',
            // use name as label
            labelField: 'CodeName',
            // use id as value
            valueField: 'CodeValue',
            immediate: true,
            optionFilterProp: 'label',
            showSearch: true,
          },
        },
        {
          field: 'Remark',
          label: '备注',
          required: false,
          component: 'InputTextArea',
          componentProps: {},
        },
        {
          field: 'CreatedTime',
          label: '创建时间',
          required: false,
          component: 'DatePicker',
          componentProps: {
            disabled: true,
            style: {
              width: '100%',
            },
          },
        },
      ];

      const [
        registerForm,
        {
          resetFields,
          getFieldsValue,
          appendSchemaByField,
          removeSchemaByField,
          setFieldsValue,
          validate,
        },
      ] = useForm({
        /** 表单配置 */
        schemas: schemas,
        /** 扩展 form 组件，增加 label 宽度，表单内所有组件适用，可以单独在某个项覆盖或者禁用 */
        labelWidth: 120,
        /** label 布局 */
        labelAlign: props.labelAlign,
        /** 紧凑类型表单，减少 margin-bottom */
        compact: props.compact,
        /** 向表单内所有组件传递 size 参数,自定义组件需自行实现 size 接收 */
        size: props.size,
        /** 向表单内所有组件传递 disabled 属性，自定义组件需自行实现 disabled 接收 */
        disabled: props.disabled,
        /** 是否显示操作按钮(重置/提交) */
        showActionButtonGroup: false,
        baseColProps: {
          offset: 3,
          // span: 24,
          xs: 16, // <576px
          sm: 16, // ≥576px
          md: 16, // ≥768px
          lg: 16, // ≥992px
          xl: 16, // ≥1200px
          xxl: 16, // ≥1600px
          // xxxl: 24, // ≥2000px 3.0
        },
      });
      const [register, { setModalProps, closeModal, changeLoading }] = useModalInner(
        async (data) => {
          setModalProps({
            canFullscreen: true,
            centered: false,
            maskClosable: false,
            destroyOnClose: true,
            width: '50%',
          });
          resetFields();
          changeLoading(true);
          try {
            if (data.formMode) {
              formModeRef.value = data.formMode as FormModeEnum;
              FormModeEntityRef.value = new FormModeEntity(formModeRef.value);
            }

            if (data.record) {
              setFieldsValue({
                ...data.record,
              });
            }
          } finally {
            changeLoading(false);
          }
        },
      );

      //#region "加载状态"
      const loadingRef = ref(false);
      /** 开启加载状态 */
      function openLoading() {
        changeLoading(true);
        setModalProps({ confirmLoading: true, cancelButtonProps: { loading: true } });
        loadingRef.value = true;
      }
      /** 关闭加载状态 */
      function closeLoading() {
        changeLoading(false);
        setModalProps({ confirmLoading: false, cancelButtonProps: { loading: false } });
        loadingRef.value = false;
      }
      //#endregion

      /** 处理关闭按钮 */
      async function handleClose() {
        openLoading();

        const { closeFunc } = props;
        try {
          if (closeFunc && isFunction(closeFunc)) {
            const result = await closeFunc(FormModeEntityRef.value.FormMode, getFieldsValue());
            return result;
          }
        } finally {
          closeLoading();
        }
        return true;
      }
      /** 处理确定按钮 */
      async function handleOk() {
        const data = await validate();
        if (!data) return;
        openLoading();

        const { createApi, updateApi, deleteApi, submitFunc, reloadFunc } = props;
        try {
          if (submitFunc && isFunction(submitFunc)) {
            const canClose = await submitFunc(FormModeEntityRef.value.FormMode, getFieldsValue());
            if (canClose) {
              closeModal();
            }
          } else {
            switch (FormModeEntityRef.value.FormMode) {
              case FormModeEnum.Ok:
              case FormModeEnum.ReadOnly:
                closeModal();
                break;
              case FormModeEnum.Add:
                if (createApi && isFunction(createApi)) {
                  const result = await createApi([getFieldsValue()]);
                  closeModal();
                  if (reloadFunc && isFunction(reloadFunc)) {
                    await reloadFunc();
                  }
                  if (result?.Type === 200) {
                    createMessage.success(t('common.successText'));
                  }
                }
                break;
              case FormModeEnum.Edit:
                if (updateApi && isFunction(updateApi)) {
                  const result = await updateApi([getFieldsValue()]);
                  closeModal();
                  if (reloadFunc && isFunction(reloadFunc)) {
                    await reloadFunc();
                  }
                  if (result?.Type === 200) {
                    createMessage.success(t('common.successText'));
                  }
                }
                break;
              case FormModeEnum.Delete:
                if (deleteApi && isFunction(deleteApi)) {
                  const formData = getFieldsValue();
                  const result = await deleteApi([formData.Id]);
                  closeModal();
                  if (reloadFunc && isFunction(reloadFunc)) {
                    await reloadFunc();
                  }
                  if (result?.Type === 200) {
                    createMessage.success(t('common.successText'));
                  }
                }
                break;
              case FormModeEnum.Search:
                closeModal();
                break;
            }
          }
        } finally {
          closeLoading();
        }
      }

      function setDefaultDescription(arr: string[]) {
        if (arr.length > 0) {
          setFieldsValue({
            Description: arr.join('：,'),
          });
        } else {
          setFieldsValue({
            Description: '',
          });
        }
      }

      return {
        loadingRef,
        t,
        register,
        registerForm,
        FormModeEntityRef,
        handleOk,
        handleClose,
      };
    },
  });
</script>
<style lang="less">
  .context-menu {
    z-index: 8888 !important;
  }
</style>
